"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 系统内部使用工具
Case Name   : 执行gs_install命令安装数据库，设置启动超时等待时间，指定参数--time-out=1
Create At   : 2022/01/06
@zou_jialiang0501129488
Description :
    1.下载解压数据库安装包
    2.配置xml文件
    3.创建初始用户及修改文件属性
    4.gs_preinstall预安装：
    ./gs_preinstall -U [初始用户] -G [初始用户组] -X [xml配置文件路径]
    --sep-env-file=[env文件路径] --non-interactive --skip-hostname-set
    5.gs_install安装数据库：
    gs_install -X [xml配置文件路径] --time-out=1
    6.清理环境
    gs_uninstall 删除数据库：gs_uninstall --delete-data
    删除数据库相关目录：
    rm -rf [数据库相关目录]
Expect      :
    1.下载解压成功
    2.配置成功
    3.用户创建成功且文件属性修改成功
    4.预安装成功
    5.启动不成功，报错启动超时
    6.清理成功
History     :
    modified by @daiguatutu at 2022-11-1:添加参数skip-hostname-set,避免破坏hosts文件
"""
import os
import re
import time
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger

Constant = Constant()


class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.pri_root_node = Node('PrimaryRoot')
        self.pri_node = Node('PrimaryDbUser')
        self.common = Common()
        self.u_name = 'gs_install_0014'
        instance_path = macro.DB_INSTANCE_PATH
        for num in range(macro.DB_INSTANCE_PATH.count('/') - 1):
            instance_path = os.path.dirname(instance_path)
        self.dir_path = os.path.join(instance_path, self.u_name)
        self.package_path = os.path.join(self.dir_path, 'pkg')
        self.conf_path = os.path.join(self.dir_path, 'config')
        self.data_path = os.path.join(self.dir_path, 'cluster')
        self.xml_path = os.path.join(self.conf_path, 'single.xml')
        self.env_path = os.path.join(self.conf_path, 'env')
        self.script_path = os.path.join(self.package_path, 'script')
        wget_result = self.pri_node.sh(f"wget {macro.FTP_PATH} "
                                       f"-c -t2 -T30").result()
        res = re.search(Constant.wget_connect_success_msg, wget_result)
        self.log.info(res)
        self.assertIsNotNone(re.search(Constant.wget_connect_success_msg,
                                       wget_result))

    def test_gs_install(self):
        text = '----step1:下载解压数据库安装包 expect:下载解压成功----'
        self.log.info(text)
        self.common.check_load_msg(self.pri_root_node, self.pri_node,
                                   self.package_path, self.conf_path)

        test = '----查看主机名----'
        self.log.info(test)
        node_name = self.common.get_sh_result(self.pri_root_node, "uname -n")
        self.assertIsNotNone(node_name, '执行失败:' + text)

        test = '----查询系统未使用端口----'
        self.log.info(test)
        port = self.common.get_not_used_port(self.pri_node)
        self.assertNotEqual(0, port, '执行失败:' + text)

        text = '----step2:配置xml文件 expect:配置成功----'
        self.log.info(text)
        gaussdb_app_path = os.path.join(self.data_path, 'app')
        gaussdb_log_path = os.path.join(self.data_path, 'gaussdb_log')
        tmpmppdb_path = os.path.join(self.data_path, 'tmp')
        gaussdb_tool_path = os.path.join(self.data_path, 'tool')
        data_node1 = os.path.join(self.data_path, 'dn1')
        self.common.scp_file(self.pri_root_node, 'single.xml', self.conf_path)
        xml_cmd = f"sed -i 's#v_nodeNames#{node_name}#g' {self.xml_path};" \
            f"sed -i 's#v_gaussdbAppPath#{gaussdb_app_path}#g' " \
            f"{self.xml_path};" \
            f"sed -i 's#v_gaussdbLogPath#{gaussdb_log_path}#g' " \
            f"{self.xml_path};" \
            f"sed -i 's#v_tmpMppdbPath#{tmpmppdb_path}#g' {self.xml_path};" \
            f"sed -i 's#v_gaussdbToolPath#{gaussdb_tool_path}#g' " \
            f"{self.xml_path};" \
            f"sed -i 's#v_corePath#{macro.DB_CORE_PATH}#g' {self.xml_path};" \
            f"sed -i 's#v_db_host#{self.pri_node.db_host}#g' " \
            f"{self.xml_path};" \
            f"sed -i 's#v_dataPortBase#{port}#g' {self.xml_path};" \
            f"sed -i 's#v_dataNode1#{data_node1}#g' {self.xml_path};" \
            f"cat {self.xml_path}"
        self.log.info(xml_cmd)
        result = self.common.get_sh_result(self.pri_root_node, xml_cmd)
        self.log.info(result)
        msg_list = [node_name, self.data_path, f"{port}", self.pri_node.db_host]
        for msg in msg_list:
            self.assertIn(msg, result, '执行失败:' + text)

        text = '----step3:创建初始用户并修改密码 expect:创建成功----'
        self.log.info(text)
        self.common.create_user(self.pri_root_node, self.u_name)
        file_own = f'chown -R {self.u_name}:{self.u_name} ' \
                   f'{self.dir_path};'
        self.log.info(file_own)
        file_msg = self.common.get_sh_result(self.pri_root_node, file_own)
        self.assertEqual('', file_msg, '执行失败:' + test)

        text = '----step4:执行gs_preinstall命令 expect:预安装成功----'
        self.log.info(text)
        preinstall_cmd = f"cd {self.script_path};" \
                         f"./gs_preinstall -U {self.u_name} " \
                         f"-G {self.u_name} -X {self.xml_path} " \
                         f"--sep-env-file={self.env_path} " \
                         f"--non-interactive --skip-hostname-set"
        self.log.info(preinstall_cmd)
        msg = self.common.get_sh_result(self.pri_root_node, preinstall_cmd)
        self.assertIn(Constant.preinstall_success_msg, msg, '执行失败:' + text)

        text = '-----step5:执行gs_install --time-out=1命令 expect:启动失败,后台启动成功-----'
        self.log.info(text)
        su_cmd = f"su - {self.u_name}"
        install_cmd = f"gs_install -X {self.xml_path} --time-out=1"
        execute_cmd = f'''expect <<EOF
                        set timeout 300
                        spawn {su_cmd}
                        expect "$"
                        send "source {self.env_path}\\n"
                        expect "$"
                        send "{install_cmd}\\n"
                        expect "Please enter password for database:"
                        send "{macro.COMMON_PASSWD}\\n"
                        expect "Please repeat for database:"
                        send "{macro.COMMON_PASSWD}\\n"
                        expect eof\n''' + '''EOF'''
        self.log.info(execute_cmd)
        exec_msg = self.common.get_sh_result(self.pri_root_node, execute_cmd)
        self.assertNotIn(Constant.install_success_msg, exec_msg, '安装错误')
        time.sleep(60)

        check_cmd = f"su - {self.u_name} -c 'source {self.env_path};" \
                    f"gs_om -t status --detail;'"
        msg = self.common.get_sh_result(self.pri_root_node, check_cmd)
        self.assertIn('P Primary Normal', msg, '执行失败' + text)

    def tearDown(self):
        self.log.info('----step6:清理环境----')
        kill_flag = False
        dir_flag = False
        user_flag = False
        text_1 = '----gs_uninstall卸载数据库 expect:卸载成功----'
        self.log.info(text_1)
        execute_cmd = f'su - {self.u_name} <<EOF\n' \
                      f'source {self.env_path};' \
                      f'gs_uninstall --delete-data;\n' \
                      f'EOF'
        self.log.info(execute_cmd)
        uninstall_msg = self.common.get_sh_result(self.pri_root_node,
                                                  execute_cmd)

        kill_cmd = f"ps -u {self.u_name} | grep -v PID | " \
                   f"awk \'{{{{print $1}}}}\' | xargs kill -9;" \
                   f"ipcs -m|awk '{{{{if($3~/^[0-9]+$/) {{{{print $2}}}}}}}}'" \
                   f" | xargs -I {{{{}}}} ipcrm -m {{{{}}}};" \
                   f"ipcs -s|awk '{{{{if($3~/^[0-9]+$/) {{{{print $2}}}}}}}}'" \
                   f" | xargs -I {{{{}}}} ipcrm -s {{{{}}}};sync;" \
                   f"echo 3 > /proc/sys/vm/drop_caches"
        self.log.info(kill_cmd)
        for count in range(10):
            pri = self.common.get_sh_result(self.pri_root_node, kill_cmd)
            if pri:
                self.log.info('process killed')
                kill_flag = True
                break
        text_3 = '----删除用户及数据准备目录 expect:成功----'
        self.log.info(text_3)
        check_cmd = f'rm -rf {self.dir_path};' \
                    f'if [ -d {self.dir_path} ]; ' \
                    f'then echo "exists"; else echo "not exists"; fi'
        self.log.info(check_cmd)
        for count in range(10):
            pri = self.common.get_sh_result(self.pri_root_node, check_cmd)
            if 'not exists' in pri:
                self.log.info('file deleted')
                dir_flag = True
                break
        usr_cmd = f'userdel -rf {self.u_name};id {self.u_name}'
        for count in range(10):
            pri = self.common.get_sh_result(self.pri_root_node, usr_cmd)
            if 'no such user' in pri:
                self.log.info('user deleted')
                user_flag = True
                break
        self.assertIn(Constant.uninstall_success_msg, uninstall_msg, '卸载失败')
        self.assertTrue(kill_flag, '清理环境失败')
        self.assertTrue(dir_flag, '清理环境失败')
        self.assertTrue(user_flag, '清理环境失败')
        self.log.info(f'-----{os.path.basename(__file__)} finish-----')
